package com.example.onlinemusic.controller;

import com.example.onlinemusic.mapper.LoveMusicMapper;
import com.example.onlinemusic.mapper.MusicMapper;
import com.example.onlinemusic.model.Music;
import com.example.onlinemusic.model.User;
import com.example.onlinemusic.tools.Constant;
import com.example.onlinemusic.tools.ResponseBodyMessage;
import org.apache.ibatis.binding.BindingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 74646
 * Date: 2022-08-22
 * Time: 22:43
 */

@RestController
@RequestMapping("/music")
public class MusicController {

//    private String SAVE_PATH = "E:/Test/Gitee/java-project_code/onlinemusic/SaveMusic/" ;

    // 在配置文件中添加歌曲路径
    @Value("${music.local.path}")
    private String SAVE_PATH;

    @Autowired
    private MusicMapper musicMapper;

    @Autowired
    private LoveMusicMapper loveMusicMapper;

    /**
     *  上传音乐
     *  请求路径：/music/upload
     * @param singer 上传歌手
     * @param file 上传歌曲
     * @param request 请求，验证是否登录
     * @return 返回true表示上传成功，返回false表示上传失败
     */
    @RequestMapping("/upload")
    public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer,
                                                    @RequestParam ("filename")MultipartFile file, HttpServletRequest request, HttpServletResponse response){

        // 1. 检查是否登录
        HttpSession session = request.getSession(false);
        if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
            System.out.println("没有登录");
            return  new ResponseBodyMessage<>(-200,"请登录后再进行上传",false);
        }

        // 2. 获取的是文件的完整名称，包括文件名称+文件拓展名
        String fileNameAndType = file.getOriginalFilename();

        // 3. 查询数据库中是否存在当前要上传的音乐（歌曲名+歌手）
        /**
         *  获取标题（标题不包含后缀.mp3）
         *  使用 lastIndexOf 从后向前找第一个 .
         */
        int index = fileNameAndType.lastIndexOf(".");
        String title = fileNameAndType.substring(0,index);

        // 使用 list 存放歌曲，获取歌曲名
        List<Music> list = musicMapper.selectBytitle(title);
        if(list != null){
            for(Music music : list){
                // 判断当前上传的歌曲+歌手在数据库中是否存在，如果存在则上传失败（歌曲名+歌手 不能重复）
                if(music.getSinger().equals(singer)){
                    return new ResponseBodyMessage<>(-200,"上传失败，数据库中存在此歌曲，不能重复上传",false);
                }
            }
        }

        // 2. 数据上传到服务器
//        System.out.println("fileNameAndType:"+fileNameAndType);

        // 上传文件路径
        String path = SAVE_PATH+fileNameAndType;

        // 上传文件
        File dest = new File(path);
        if(!dest.exists()){
            //如果路径不存在就创建目录
            dest.mkdir();
        }
        try {
            // 将接收到的文件传输到给定目标路径
            file.transferTo(dest);
            //System.out.println("文件上传成功");
//            return new ResponseBodyMessage<>(200,"上传成功",true);

        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseBodyMessage<>(-200,"上传失败，服务器出现问题",false);
        }

        // 3. 判断上传的文件是否为mp3文件（判断是否存在 TAG 字符）
        File file1 = new File(path);
        byte[] bytes = null;
        try {
            bytes = Files.readAllBytes(file1.toPath());
            if(bytes == null){
                return new ResponseBodyMessage<>(-200,"上传失败，文件不存在",false);
            }
            String str = new String(bytes);
            if(!str.contains("TAG")){
                file1.delete();
                return new ResponseBodyMessage<>(-200,"上传的文件不是mp3文件",false);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseBodyMessage<>(-200,"上传失败，服务器出现问题",false);
        }

        // 4. 将数据上传到数据库中（1. 准备数据      2. 调用 insert）


        /**
         *  获取 userId
         * 登录成功后将用户信息写到 session 中，通过 session 中key值(Constant.USERINFO) 就可以获取到对应的 value 值(用户信息)
         */
        User user = (User)session.getAttribute(Constant.USER_SESSION_KEY);
        // 获取用户Id
        int userId = user.getUserId();

        /**
         *  url 的作用： 播放音乐->发送 http 请求
         */
        String url = "/music/get?path="+title; // 将 url 存入数据库时不用加后缀 .mp3，在取数据的时候加一个后缀就可以了

        /**
         *  获取上传的时间
         *  将获取的时间格式化为：年-月-日 的形式
         */
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String time = simpleDateFormat.format(new Date());

        // 插入数据
        try {
            int ret = musicMapper.insert(title,singer,time,url,userId);
            if(ret == 1){
                // 数据插入成功
                // 这里应该跳转到音乐列表页面
                response.sendRedirect("/list.html");
                return new ResponseBodyMessage<>(200,"数据库上传成功",true);
            }else{
                // 数据插入失败
                return new ResponseBodyMessage<>(-200,"数据库上传失败",false);
            }
        }catch (BindingException | IOException e){
            // 数据库上传失败，将上传到文件夹中的数据删除
            dest.delete();
            e.printStackTrace();
            return new ResponseBodyMessage<>(-200,"数据库上传失败",false);
        }
    }

    /**
     *  播放音乐
     *  请求路径：/music/get?get=xxx.mp3
     * @param path
     * @return
     */
        @RequestMapping("/get")
        public ResponseEntity<byte[]> playMusic(@RequestParam String path) {
        File file = new File(SAVE_PATH+path);
        byte[] bytes = null;
            try {
                bytes  = Files.readAllBytes(file.toPath()); // 将文件路径中的文件以字节的形式读取，放到 bytes 数组中
                if(bytes == null){
                    // 如果没有读取的文件，则返回状态码 400
                    return ResponseEntity.badRequest().build();
                }
                // 成功读取到文件
                return ResponseEntity.ok(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 如果没有读取的文件，则返回状态码 400
            return ResponseEntity.badRequest().build();
    }

    /**
     * 删除单个音乐
     * 请求路径：/music/delete?musicId=x
     * @param musicId
     * @return
     */
    @RequestMapping("/delete")
    public ResponseBodyMessage<Boolean> deleteMusicByMusicId(@RequestParam String musicId){
        /**
         * 1. 检查待删除的音乐是否存在
         * 2. 如果存在要删除的音乐
         *      1. 删除数据库中的数据
         *      2. 删除服务器上的数据
         */
        // 检查待删除的音乐是否存在
        Music music = musicMapper.findMusicById(Integer.parseInt(musicId));
        if(music == null){
            System.out.println("在控制台打印日志：没有要删除的音乐id");
            return new ResponseBodyMessage<>(-200,"要删除的音乐不存在",false);
        }else{
            // 调用 musicMapper 接口中的 deleteMusicById 方法删除数据库中的数据
           int ret = musicMapper.deleteMusicById(Integer.parseInt(musicId));

           if(ret == 1){
               // 成功删除数据库中的数据
               /*int index = music.getUrl().lastIndexOf("=");
               String fileName = music.getUrl().substring(index+1);*/

               String fileName = music.getTitle();
               // 根据存放音乐的路径删除服务器中的数据
               File file = new File(SAVE_PATH+fileName+".mp3");
               System.out.println("在控制台打印日志：当前音乐的路径："+file.getPath());
                //对删除服务器中的数据进行判断
               if(file.delete()){
                   // 同步删除 lovemusic 表中的音乐
                   loveMusicMapper.deleteLoveMusicByMusicId(Integer.parseInt(musicId));
                   // 删除成功
                   return new ResponseBodyMessage<>(200,"音乐删除成功",true);
               }else{
                   return new ResponseBodyMessage<>(-200,"服务器中的音乐删除失败",false);
               }
           }else{
               return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
           }
        }
    }

    /**
     *  批量删除选中的音乐
     *  请求路径：/music/deleteSel
     * @param musicId
     * @return
     */
    @RequestMapping("/deleteSel")
    public ResponseBodyMessage<Boolean> deleteSelMusic(@RequestParam("musicId[]") List<Integer> musicId) {
        System.out.println("在控制台打印日志：所有音乐的 Id："+musicId);
        int sum = 0; // 统计删除的音乐
        for (int i = 0; i < musicId.size(); i++) {
            Music music = musicMapper.findMusicById(musicId.get(i));
            if (music == null) {
                System.out.println("没有要删除的音乐id");
                return new ResponseBodyMessage<>(-200, "要删除的音乐不存在", false);
            }
            int ret = musicMapper.deleteMusicById(musicId.get(i));
            if (ret == 1) {
                // 成功删除数据库中的数据
                String fileName = music.getTitle();
                // 根据存放音乐的路径删除服务器中的数据
                File file = new File(SAVE_PATH + fileName + ".mp3");
                System.out.println("当前音乐的路径：" + file.getPath());
                //对删除服务器中的数据进行判断
                if (file.delete()) {
                    // 同步删除 lovemusic 表中的音乐
                    loveMusicMapper.deleteLoveMusicByMusicId(musicId.get(i));
                    // 成功删除一条数据，sum 就加上 ret（数据库中成功删除）
                    sum += ret;
                } else {
                    return new ResponseBodyMessage<>(-200, "服务器中的音乐删除失败", false);
                }
            }else{
                return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
            }
        }
        if(sum == musicId.size()){
            // 选中的数据全部删除成功
            System.out.println("在控制台打印日志：选择中的歌曲删除成功");
            return new ResponseBodyMessage<>(200,"音乐删除成功",true);
        }else{
            System.out.println("在控制台打印日志：选择中的歌曲删除失败");
            return new ResponseBodyMessage<>(-200,"音乐删除失败",false);
        }
    }

    /**
     *  查询音乐
     * @param musicName
     * @return
     */
    @RequestMapping("/findmusic")
    public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false) String musicName){
        List<Music> musicList = null;
        if(musicName != null){
            // 模糊查询，根据歌曲名查询指定的歌曲
            musicList = musicMapper.findMusicByName(musicName);
        }else{
            // 查询所有的音乐
            musicList = musicMapper.findMusic();
        }
        // 查询成功，返回查询到的音乐信息
        return new ResponseBodyMessage<>(200,"查询成功",musicList);
    }
}



